fix(contracts): state the scroll keyboard clip once for every platform - #2537
Conversation
Size Report
Startup median (7 runs, lower is better):
|
|
|
No actionable findings on 1b8548a. The shared contract and Apple surface extraction preserves the previously reviewed source, with the dispatch changes correctly left in the dependent PRs. Typed errors, response fields, MCP schema, fixtures, help, and docs are aligned for this layer. Current checks pass and there are no conflicts. Ready for human review and merge. |
…nd keep the runner's message The Apple scroll owner rebuilt the refusal per command, discarding the runner's measured message and carrying an unmeasured variant of the error builder for it. The shared reason and hint are now one frozen object in scroll-gesture; the Apple owner adds it to the runner's own error (matched on the typed runner code, transport details kept), and the error builder takes a plain measured occlusion, which only Android produces in-process. The help text names the behaviour in one clause; the hint carries the recovery at the moment it matters.
|
Reviewed the whole stack and pushed a simplification at What changed here
Net −41 lines on this layer, same reason and hint on every path. Tried and reverted: hosting the details in
|
|
No actionable findings on 673ea45. The Apple wrapper preserves the runner message and transport details while adding the shared reason and hint, including after journal recovery. Coverage failed in the unchanged snapshot-source lifecycle fixture: "a crashed helper is removed and the next request starts a fresh helper" exceeded its dispatch deadline and raised bridge-connect-deadline. This looks unrelated to the scroll delta, but CI needs to pass before merge. The ready-for-human label remains valid. Failure: https://github.com/callstack/agent-device/actions/runs/34748827127/job/103701514870 |
Summary
First layer of #2500: the rule that keeps a scroll's swipe out of the keyboard, stated once in TypeScript, with the golden table both native runners read. iOS implements it in #2503 and Android in #2514, so nothing here moves a gesture yet.
clipScrollViewportAboveKeyboardis the whole decision: a keyboard that reaches the swipe's centre line takes the band below it, and when what remains cannot carry a swipe the command refuses withscrollKeyboardOccludesSurfaceErrorrather than scrolling a surface the keys own.contracts/fixtures/scroll-keyboard-policy.jsonis the cross-language table, so the Swift and Java lanes assert against the same rows instead of each platform inventing its own thresholds.Behaviour stated here
keyboardAvoidedandkeyboardMinYjoin a scroll response only when the clip ran, and the CLI help, MCP output schema and command docs name them here, so both platforms answer with one shape.fill/scroll/fillloop;keyboard dismissstays an explicit command.Validation
pnpm checkgreen at1b8548af6d, which covers the golden parity table (18 rows, including the Android-shapedadjustPan window with only 88px of 900px left above the IME is refusedand the iOS-shapedlandscape keyboard leaving 28pt of a 402pt axis is refused instead of swiping under the keys), the Apple-side mapping tests, MCP metadata and the production-exports lane.No device run belongs to this layer — it dispatches nothing. The live simulator and emulator evidence for the paths it states is posted on #2503 and #2514.
Size
11 files, 615 gross lines: one shared module, its golden table, and the surface that names its two response keys.
Part of the #2500 stack: this PR -> #2503 (iOS runner) -> #2514 (Android). Do not merge out of order.